﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CTC;

namespace CTCTest
{
    public partial class MasterForm : Form
    {
        private CTCMaster Master = null;
        private UInt32 MasterProductID = 0;
        private byte[] MasterDeviceID = new byte[16];
        private UInt32 SlaveProductID = 0;
        private byte[] SlaveDeviceID = new byte[16];
        private UInt16 SlaveVersion = 0;
        /// <summary>
        /// 游戏机投的币
        /// </summary>
        private UInt32 SlaveCoinIn = 0;
        /// <summary>
        /// 游戏机出的票
        /// </summary>
        private UInt32 SlaveTicketOut = 0;
        public MasterForm()
        {
            InitializeComponent();
            InstEnadle(false);
        }
        private void InstEnadle(bool ok)
        {
            btn_MeterData.Enabled = ok;
            btn_CoinIn.Enabled = ok;
            btn_SetCoin.Enabled = ok;
            btn_QueryCoin.Enabled = ok;
            btn_SelectChannel.Enabled = ok;
            btn_ChangeState.Enabled = ok;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 定义一个字符串数组，并将获取到的电脑上串口名字赋值给它
            string[] ports = SerialPort.GetPortNames();

            // 遍历并打印所有找到的串口
            foreach (var port in ports)
            {
                comboBox_Serial.Items.Add(port);
            }
            //if (comboBox_Serial.Items.Count > 0)
            //{
            //    comboBox_Serial.SelectedIndex = 1;
            //}
            lab_MasterProductID.Text = String.Format("MasterProductID:{0}", MasterProductID);
            lab_MasterDeviceID.Text = String.Format("MasterDeviceID:{0}", CRC.ToHexStringTrim(MasterDeviceID));

        }
        private void btn_open_Click(object sender, EventArgs e)
        {
            if (comboBox_Serial.Items.Count == 0)
            {
                MessageBox.Show("没有可用串口", "提醒", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (comboBox_Serial.SelectedIndex == -1)
            {
                MessageBox.Show("请选择要打开的串口", "提醒", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            btn_open.Enabled = false;
            Master = new CTCMaster(comboBox_Serial.SelectedItem.ToString(), MasterProductID, SlaveDeviceID);
            Master.DebugLogI += LogI;
            Master.DebugLogE += LogE;
            Master.OnHandshake += Master_OnHandshake;
            Master.OnStateChange += Master_OnStateChange;
            Master.OnCoinInRsp += Master_OnCoinInRsp;
            Master.OnPhysicalReport += Master_OnPhysicalReport;
            Master.OnMeterData += Master_OnMeterData;
            Master.OnQueryCoin += Master_OnQueryCoin;
            Master.OnReward += Master_OnReward;
            Master.OnAtmosphere += Master_OnAtmosphere;
            Master.OnSendFail += Master_OnSendFail;
            Master.OnSlaveStateChange += Master_OnSlaveStateChange;
            Master.Open();
        }

        private void Master_OnSlaveStateChange(byte player, byte[] data)
        {
            LogI(player, String.Format("Slave状态变更  {0}  {1}", data[0], CRC.ToHexStringTrim(data[1], data[2])));
        }

        /// <summary>
        /// 发送数据失败回调
        /// </summary>
        /// <param name="state">失败状态  CTC_CMD_ACK</param>
        /// <param name="player">P位</param>
        /// <param name="inst">指令</param>
        /// <param name="data">数据</param>
        private void Master_OnSendFail(byte state, byte player, byte[] inst, byte[] data)
        {
            LogI(player, String.Format("发送失败-指令:{0}", CRC.ToHexStringTrim(inst)));
        }

        private void Master_OnAtmosphere(byte player, byte[] data)
        {
            /**
             * 事件等级	2字节	0开始,数字越大氛围越强烈
             * 将要奖励类型	1字节	0=奖励彩票,1=奖励蓝票,10=游戏任务得分,100=奖励实物
             * 将要奖励数量	4字节	产生的奖励相关的数量
             */
            UInt16 level = CRC.BytesToUint16(data[0], data[1]);
            byte typpe = data[2];
            UInt32 number = CRC.BytesToUint32(data[3], data[4], data[5], data[6]);
            LogI(player, String.Format("氛围事件:{0}   {1}   {2}", level, typpe, number));
        }

        private void Master_OnReward(byte player, byte[] data)
        {
            /**
             * 奖励类型	1字节	0=奖励彩票,1=奖励蓝票,10=游戏任务得分
             * 奖励数量	4字节	奖励的数量
             */
            byte type = data[0];
            UInt32 number = CRC.BytesToUint32(data[1], data[2], data[3], data[4]);
            if (type == 0)
            {
                SlaveTicketOut += number;
            }
            LogI(player, String.Format("游戏奖励:{0}   {1}", type, number));
            try
            {
                this.Invoke((MethodInvoker)delegate
                {
                    lab_SlaveTicketOut.Text = String.Format("SlaveTicketOut:{0}", SlaveTicketOut);
                });
            }
            catch { }
        }

        private void Master_OnQueryCoin(byte player, byte[] data)
        {
            /**
             * 每局币数	2字节	每局游戏需要的投币数(投币器的脉冲数)
             */
            LogI(player, String.Format("每局币数:{0}", CRC.BytesToUint16(data)));
        }

        private void Master_OnMeterData(byte player, byte[] data)
        {
            /**
             * 5个byte为一组,一共10组50个byte
             * 0:类型
             * 1-4:数据
             * 
             * 类型
             * 0=投币总数,1=电子币总数,2=实物币总数
             * 10=出票总数,11=出电子票总数,12=出实物票总数
             * 20=出蓝票总数,21=出电子蓝票总数,22=出实物蓝票总数
             * 30=总出卡片数
             * 100=出礼品1总数,101=出实物礼品2总数,102=出实物礼品2总数,103=出实物礼品4总数,104=出实物礼品5总数,...130=出实物礼品31总数
             * 255=数据结束(无效后面不能再放有效数据)
             */
            LogI(player, String.Format("收到抄表:{0}", CRC.ToHexStringTrim(data)));
        }

        private void Master_OnPhysicalReport(byte player, byte[] data)
        {
            /**
          * 实物类型	1字节	0=实物币,2=实物彩票,2=实体蓝票,3=实体卡片,100=实物礼品1,101=实物礼品2...130=实物礼品31
          * 奖励数量	4字节	上报数量
          */
            byte type = data[0];
            UInt32 number = CRC.BytesToUint32(data[1], data[2], data[3], data[4]);
            if (type == 0)
            {
                SlaveCoinIn += number;
            }
            LogI(player, String.Format("实体数据上报:{0}   {1}", type, number));
            try
            {
                this.Invoke((MethodInvoker)delegate
                {
                    lab_SlaveCoinIn.Text = String.Format("SlaveCoinIn:{0}", SlaveCoinIn);
                });
            }
            catch { }
        }

        private void Master_OnCoinInRsp(byte player, byte[] data)
        {
            /**
            * 投币结果	1字节	0=成功接收,1=拒绝接收
            * 消费记录ID	16字节	投币时传递的交易ID
            * 消费记录ID	16字节	标识此笔交易的ID
            */
            byte[] orderID = CRC.SubByteData(data, 1, 16);
            LogI(player, String.Format("卡头投币结果:{0}   {1}", data[0], CRC.ToHexStringTrim(orderID)));
        }

        private void Master_OnStateChange(byte player, CTCClientConnState state)
        {
            this.Invoke((MethodInvoker)delegate
            {
                if (state == CTCClientConnState.Connected)
                {
                    lab_ConnState.ForeColor = Color.Green;
                    InstEnadle(true);
                }
                else
                {
                    lab_ConnState.ForeColor = Color.Red;
                    InstEnadle(false);
                }
                lab_ConnState.Text = state.ToString();
            });
        }

        private void Master_OnHandshake(byte player, byte[] data)
        {
            /**
             * 产品ID	4字节	CTC官网分配的产品ID,用于查询是哪个厂家出的什么产品
             * 设备ID	16字节	每个设备自己保证全球唯一
             * 支持的CTC协议最高版本	2字节	本设备支持的CTC协议最高版本
             * */
            SlaveProductID = CRC.BytesToUint32(data[0], data[1], data[2], data[3]);
            Array.Copy(data, 4, SlaveDeviceID, 0, 16);
            SlaveVersion = CRC.BytesToUint16(data[20], data[21]);
            LogI(player, String.Format("SlaveVsion:{0}", SlaveVersion));
            try
            {
                this.Invoke((MethodInvoker)delegate
                {
                    lab_SlaveProductID.Text = String.Format("SlaveProductID:{0}", SlaveProductID);
                    lab_SlaveDeviceID.Text = String.Format("SlaveDeviceID:{0}", CRC.ToHexStringTrim(SlaveDeviceID));
                });
            }
            catch { }
        }

        private void LogI(byte player, string msg)
        {
            try
            {
                this.Invoke((MethodInvoker)delegate
                {
                    richTextBox1.AppendText(msg + "\n");
                });
            }
            catch { }
        }
        private void LogE(byte player, string msg)
        {
            try
            {
                this.Invoke((MethodInvoker)delegate
                {
                    richTextBox1.AppendText(msg + "\n");
                });
            }
            catch { }
        }

        private void btn_MeterData_Click(object sender, EventArgs e)
        {
            Master.SendReadMeter();
        }

        private void btn_CoinIn_Click(object sender, EventArgs e)
        {
            /**
             * 投币数量	4字节	投币数量
             * 会员ID	16字节	同一张会员卡或同一个会员账户时ID相同
             * 消费记录ID	16字节	标识此笔交易的ID
             */
            Master.SendInCoin(1, new byte[16] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, new byte[16] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 });
        }

        private void MasterForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Master != null)
            {
                Master.Close();
            }
        }

        private void btn_SetCoin_Click(object sender, EventArgs e)
        {
            Master.SendSetCoinPrice(22);
        }

        private void btn_QueryCoin_Click(object sender, EventArgs e)
        {
            Master.SendQueryCoinPrice();
        }

        private void lab_SelectChannel_Click(object sender, EventArgs e)
        {
            Master.SendSelectChannel(0, 1);
        }

        private void btn_ChangeState_Click(object sender, EventArgs e)
        {
            if (Master.MasterState == 0)
            {
                Master.ChangeState(1);
            }
            else
            {
                Master.ChangeState(0);
            }

        }
    }
}
